package org.amos.filestorage.platform.ftp;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ftp.FtpConfig;
import cn.hutool.extra.ftp.FtpMode;
import org.amos.filestorage.exception.FileStorageException;
import org.amos.filestorage.platform.AbstractFilePlatform;
import org.amos.filestorage.platform.config.FtpFilePlatformConfig;
import org.junit.internal.Throwables;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.function.Consumer;

/**
 * FTP 存储
 */
public class FtpFilePlatform extends AbstractFilePlatform<FtpFilePlatformConfig> {

    private Ftp client;

    public FtpFilePlatform(String id, FtpFilePlatformConfig config) {
        super(id, config);
    }

    @Override
    public void initClient() {
        FtpConfig ftpConfig = FtpConfig.create()
                .setHost(config.getHost())
                .setPort(config.getPort())
                .setUser(config.getUser())
                .setPassword(config.getPassword())
                .setCharset(Charset.forName(config.getCharset()))
                .setConnectionTimeout(config.getConnectionTimeout())
                .setSoTimeout(config.getSoTimeout())
                .setServerLanguageCode(config.getServerLanguageCode())
                .setSystemKey(config.getSystemKey());
        client = new Ftp(ftpConfig, FtpMode.valueOf(config.getMode()));
    }

    @Override
    public String upload(byte[] bytes, String path, String type) {
        String name = FileUtil.getName(path);
        String dir = StrUtil.removeSuffix(path, name);
        try {
            client.upload(dir, name, new ByteArrayInputStream(bytes));
            return "";
        } catch (IORuntimeException e) {
            throw new FileStorageException(Throwables.getStacktrace(e));
        } finally {
            IoUtil.close(client);
        }
    }

    @Override
    public Boolean delete(String path) {
        try {
            client.delFile(getAbsolutePath(path));
            return Boolean.TRUE;
        } catch (IORuntimeException e) {
            throw new FileStorageException(Throwables.getStacktrace(e));
        }
    }


    @Override
    public Boolean exists(String path) {
        try {
            return client.existFile(getAbsolutePath(path));
        } catch (IORuntimeException e) {
            throw new FileStorageException(Throwables.getStacktrace(e));
        }
    }

    @Override
    public void download(String path, Consumer<InputStream> consumer) {
        try {
            client.cd(getAbsolutePath(path));
            try (InputStream in = client.getClient().retrieveFileStream(FileUtil.getName(path))) {
                if (in == null) {
                    throw new FileStorageException("文件下载失败，文件不存在！path：" + path);
                }
                consumer.accept(in);
            }
        } catch (IOException | IORuntimeException e) {
            throw new FileStorageException(Throwables.getStacktrace(e));
        }
    }

    /**
     * 获取远程绝对路径
     */
    public String getAbsolutePath(String path) {
        return config.getDomain() + path;
    }
}
